﻿using Microsoft.AspNetCore.Mvc;
using WH.Contracts.Systems.Login;
using WH.Model.Enums;
using WH.Services.IServices.ISystem;
using Rw.Core.Common;
using WH.Common.Cache;
using WH.Common.Config;
using WH.Common.Config.Options;
using WH.Common.Constant;
using WH.Common.DbConfig;
using WH.Common.Handler;
using WH.Common.Helper;
using System;
using System.Linq;
using System.Threading.Tasks;

namespace WH.WebApi.Controllers.Systems
{
    /// <summary>
    /// 登陆接口
    /// </summary>
    [Route("Login"), ApiController]
    public class LoginController : BaseController
    {
        private readonly ICaching _caching;
        private readonly IUserService _userService;
        private readonly IConfigurationCenter _configurationCenter;
        //private readonly ISysConfigService _sysConfigService;

        private readonly JwtsettingOptions _refreshJwtSettingOption;
        private readonly JwtsettingOptions _jwtSettingOption;

        /// <summary>
        /// 
        /// </summary>
        public LoginController(
            ICaching caching,
            IUserService userService,
            IConfigurationCenter configurationCenter
            //ISysConfigService sysConfigService
            )
        {
            _caching = caching;
            _userService = userService;
            _configurationCenter = configurationCenter;
            //_sysConfigService = sysConfigService;

            _refreshJwtSettingOption = new JwtsettingOptions
            {
                Audience = _configurationCenter.JwtsettingOptions.RefreshAudience,
                Issuer = _configurationCenter.JwtsettingOptions.Issuer,
                Secret = _configurationCenter.JwtsettingOptions.Secret,
                Expires = _configurationCenter.JwtsettingOptions.RefreshExpires,
            };

            _jwtSettingOption = new JwtsettingOptions
            {
                Audience = _configurationCenter.JwtsettingOptions.Audience,
                Issuer = _configurationCenter.JwtsettingOptions.Issuer,
                Secret = _configurationCenter.JwtsettingOptions.Secret,
                Expires = _configurationCenter.JwtsettingOptions.Expires,
            };
        }


        /// <summary>
        /// 登陆请求，获取access_token
        /// </summary>
        /// <param name="param"></param>
        /// <returns></returns>
        [HttpPost("")]
        public async Task<ResultResponse<LoginOutputDto>> LoginAsync([FromBody] LoginInputDto param)
        {
            if (!ModelState.IsValid)
            {
                return Error<LoginOutputDto>("账号密码格式有误，请重新输入");
            }

            var key = $"{BusinessFunction.CaptchaCacheKey}:{param.Identity}";
            //验证验证码
            var cacheCode = _caching.Get<string>(key);

            //登录成功删除验证码本地缓存
            _caching.Remove(key);

            if (cacheCode is null || !Md5.MD5Hash(param.Code.ToLower()).Equals(cacheCode))
            {
                return Error<LoginOutputDto>("验证码错误，请重新输入");
            }

            //验证用户名密码
            var user = param.UserAccount.Trim();
            var password = param.Password.Trim();

            password = SecurityHelper.FrontendAesDecrypt(password);

            //var user = SecurityHelper.FrontendStorage(param.UserAccount)?.Trim();
            //var password = SecurityHelper.FrontendStorage(param.Password)?.Trim();

            var checkPair = await _userService.CheckLoginAsync(user, password);
            if (!checkPair.IsSucceed || checkPair.Data is null)
            {
                return Error<LoginOutputDto>(checkPair.Msg);
            }

            if (checkPair.Data is not null && checkPair.Data.AccessType != (int?)UserAccessTypeEnum.System)
            {
                return Error<LoginOutputDto>("当前用户类型错误，请检查");
            }

            var userEntity = checkPair.Data;
            var jwtModel = new JwtTokenModel
            {
                UserId = userEntity.Id,
                UserAccount = userEntity.Account,
                Name = userEntity.Name ?? string.Empty,
                PhoneNumber = userEntity.PhoneNumber ?? string.Empty,
                //DutyId = userEntity.DutyId ?? string.Empty,
                HeadImg = string.IsNullOrWhiteSpace(userEntity.AvatarUrl) ? BusinessFunction.DefaultAvatarSrc : userEntity.AvatarUrl,
                RoleId = userEntity.RoleId ?? string.Empty,
                OrganizationId = userEntity.OrganizationId,

            };

            var data = await GenerateTokenAsync(jwtModel);


            return Success(data, checkPair.Msg);
        }

        /// <summary>
        /// 登陆请求，获取access_token
        /// </summary>
        /// <param name="param"></param>
        /// <returns></returns>
        [HttpGet("LinkTo")]
        public async Task<IActionResult> LinkToAsync([FromQuery] LinkToInputDto param)
        {
            //验证用户名密码
            var user = param.UserAccount.Trim();
            var password = param.Password.Trim();

            //var user = SecurityHelper.FrontendStorage(param.UserAccount)?.Trim();
            //var password = SecurityHelper.FrontendStorage(param.Password)?.Trim();

            var checkPair = await _userService.CheckLoginAsync(user, password);
            if (!checkPair.IsSucceed || checkPair.Data is null)
            {
                return new JsonResult(Error<LoginOutputDto>(checkPair.Msg));
            }

            if (checkPair.Data is not null && checkPair.Data.AccessType != (int?)UserAccessTypeEnum.External)
            {
                return new JsonResult(Error("当前用户类型错误，请检查"));
            }

            var userEntity = checkPair.Data;
            var jwtModel = new JwtTokenModel
            {
                UserId = userEntity.Id,
                UserAccount = userEntity.Account,
                Name = userEntity.Name ?? string.Empty,
                PhoneNumber = userEntity.PhoneNumber ?? string.Empty,
                //DutyId = userEntity.DutyId ?? string.Empty,
                HeadImg = string.IsNullOrWhiteSpace(userEntity.AvatarUrl) ? BusinessFunction.DefaultAvatarSrc : userEntity.AvatarUrl,
                RoleId = userEntity.RoleId ?? string.Empty,
                OrganizationId = userEntity.OrganizationId,
            };

            var data = await GenerateTokenAsync(jwtModel);
            var linktoData = new DatabaseConfigurationProvider();
            var linktoUrl = linktoData.Appsettings.FirstOrDefault(x => x.Key == "REDIRECTTOURL");
            return Redirect($"{linktoUrl?.Value}?token={data.AccessToken}");
        }

        /// <summary>
        /// 登陆请求，获取access_token
        /// </summary>
        /// <param name="param"></param>
        /// <returns></returns>
        [HttpGet("OAuth")]
        public async Task<ResultResponse<LoginOutputDto>> OauthLoginAsync([FromQuery] OauthLoginInputDto param)
        {
            if (!ModelState.IsValid)
            {
                return Error<LoginOutputDto>("账号密码格式有误，请重新输入");
            }

            //验证用户名密码
            var user = param.UserAccount?.Trim();
            var password = param.Password?.Trim();
            //var user = SecurityHelper.FrontendStorage(param.UserAccount)?.Trim();
            //var password = SecurityHelper.FrontendStorage(param.Password)?.Trim();

            var checkPair = await _userService.CheckLoginAsync(user, password);


            if (!checkPair.IsSucceed || checkPair.Data is null)
            {
                return Error<LoginOutputDto>(checkPair.Msg);
            }

            if (checkPair.Data is not null && checkPair.Data.AccessType != (int?)UserAccessTypeEnum.External)
            {
                return Error<LoginOutputDto>("当前用户类型错误，请检查");
            }

            var userEntity = checkPair.Data;
            var jwtModel = new JwtTokenModel
            {
                UserId = userEntity.Id,
                UserAccount = userEntity.Account,
                Name = userEntity.Name ?? string.Empty,
                PhoneNumber = userEntity.PhoneNumber ?? string.Empty,
                //DutyId = userEntity.DutyId ?? string.Empty,
                HeadImg = string.IsNullOrWhiteSpace(userEntity.AvatarUrl) ? BusinessFunction.DefaultAvatarSrc : userEntity.AvatarUrl,
                RoleId = userEntity.RoleId ?? string.Empty,
                OrganizationId = userEntity.OrganizationId ?? string.Empty,
            };

            var data = await GenerateTokenAsync(jwtModel);


            return Success(data, checkPair?.Msg ?? "");
        }


        /// <summary>
        /// 刷新token
        /// </summary>
        /// <returns></returns>
        [HttpPost("refresh")]
        public async Task<ResultResponse<LoginOutputDto>> RefreshTokenAsync()
        {

            var refreshToken = Request.Headers["RefreshToken"].ToString();

            if (string.IsNullOrWhiteSpace(refreshToken))
            {
                return Unauthorized<LoginOutputDto>("RefreshToken不能为空");
            }

            //验证token，如果超过一个生命周期，则禁止刷新

            var isValid = JwtTokenHandler.ValidateToken(refreshToken, _refreshJwtSettingOption);
            if (!isValid)
            {
                return Unauthorized<LoginOutputDto>("RefreshToken无效");
            }

            var jm = JwtTokenHandler.SerializeJWT(refreshToken);


            var userEntity = await _userService.GetUser(jm.UserId);
            var jwtModel = new JwtTokenModel
            {
                UserId = userEntity.Id,
                UserAccount = userEntity.Account,
                Name = userEntity.Name ?? string.Empty,
                PhoneNumber = userEntity.PhoneNumber ?? string.Empty,
                //DutyId = userEntity.DutyId ?? string.Empty,
                HeadImg = string.IsNullOrWhiteSpace(userEntity.AvatarUrl) ? BusinessFunction.DefaultAvatarSrc : userEntity.AvatarUrl,
                RoleId = userEntity.RoleId ?? string.Empty,
                OrganizationId = userEntity.OrganizationId,
                //Industry = IndustryEnum.Medical,
                //Scene = SceneEnum.Hospital,
            };

            //生成JwtToken
            var data = await GenerateTokenAsync(jwtModel);

            return Success<LoginOutputDto>(data, "token刷新成功");
        }

        /// <summary>
        /// 生成token
        /// </summary>
        /// <param name="jwtModel"></param>
        /// <returns></returns>
        private async Task<LoginOutputDto> GenerateTokenAsync(JwtTokenModel jwtModel)
        {

            //生成JwtToken
            var accessToken = await JwtTokenHandler.IssueToken(_jwtSettingOption, jwtModel);

            //生成refreshToken
            var refreshToken = await JwtTokenHandler.IssueToken(_refreshJwtSettingOption, jwtModel);

            return new LoginOutputDto
            {
                AccessToken = accessToken,
                RefreshToken = refreshToken,
                UserId = jwtModel.UserId,
                UserAccount = jwtModel.UserAccount
            };
        }


        /// <summary>
        /// 验签
        /// </summary>
        /// <param name="str"></param>
        /// <param name="signature"></param>
        /// <returns></returns>
        private bool VerificationCode(string str, string signature)
        {
            var md5 = Md5.MD5Hash(str);

            if (md5.Equals(signature, StringComparison.OrdinalIgnoreCase))
            {
                return true;
            }
            else
            {
                return false;
            }

        }
    }
}